package com.harry.basis;

import java.lang.reflect.Type;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import java.util.stream.Stream;

import org.springframework.cglib.proxy.Enhancer;
import org.springframework.cglib.proxy.NoOp;

import com.harry.configuration.ConstSettings;
import com.harry.utility.ClassUtil;
import com.harry.utility.InnerUtils;

/**
 * 1. 子类可动态获取自身泛型 2. ResourceImpl 的实例（DaoImpl、SrvImpl、MgrImpl、ApiImpl） 2.
 * 实例化时将此实例与 Inerface-Resource 做映射，方便其它业务获取
 */
public abstract class BaseGeneric<T> extends PureGeneric<T> {

	/**
	 * 实例化时如果能够获取当前泛型 则建立实例与 Inerface-Resource 映射
	 */
	public BaseGeneric() {
		if (getEntityClass() != null) {
			putScopeThis();
		}
	}

	/**
	 * 手动绑定泛型类型时 则建立实例与 Inerface-Resource 映射
	 */
	@Override
	public void bindEntityClass(Class<T> entityClass) throws Exception {
		super.bindEntityClass(entityClass);
		putScopeThis();
	}

	/**
	 * 则建立实例与 Inerface-Resource 映射
	 */
	private void putScopeThis() {
		findInterfacesFromClass(getClass()).stream().forEach(ic -> putScopeThis(ic));
	}

	/**
	 * 则建立实例与 Inerface-Resource 映射
	 * 
	 * @param ic
	 */
	private void putScopeThis(Class<?> ic) {
		if (getEntityClass() == null) {
			return;
		} else {
			String srcName = classResourceName(getEntityClass());
			String scopeKey = findInterfaceScopeKey(ic);
			Map<String, Object> scope = findInterfaceScope(scopeKey);
			if (!scope.containsKey(classResourceName(getEntityClass()))) {
				scope.put(srcName, this);
			}
		}
	}

	/**
	 * 二层映射关系：interface-resource-this 中使用的 interfaceKey
	 * 
	 * @param interfaze
	 * @return
	 */
	private String findInterfaceScopeKey(Class<?> interfaze) {
		return interfaze.getName();
	}

	/**
	 * 二层映射关系：interface-resource-this 获取 resource-this 的 map
	 * 
	 * @param scopeKey
	 * @return
	 */
	private Map<String, Object> findInterfaceScope(String scopeKey) {
		Map<String, Object> scope = SRC_SCOPE_MODULE_MAP.get(scopeKey);
		if (scope == null)
			SRC_SCOPE_MODULE_MAP.put(scopeKey, scope = new HashMap<String, Object>());
		return scope;
	}

	/**
	 * 通过 Interface 和 Entity 获取 Interface<Entity> 实例 其中： -- Interface == infc --
	 * Entity <- resouceName
	 * 
	 * @param <U>
	 * @param infc
	 * @param resourceName
	 * @return
	 */

	@SuppressWarnings("unchecked")
	public static <U extends BaseInterface> U beanOf(Class<U> infc, String resourceName) {
		Map<String, Object> scope = SRC_SCOPE_MODULE_MAP.get(infc.getName());
		if (scope != null) {
			return (U) scope.get(resourceName);
		} else {
			return null;
		}
	}

	/**
	 * 通过 Interface 和 Entity 获取 Interface<Entity> 实例 其中： -- Interface == infc --
	 * Entity == entityClass
	 * 
	 * @param <U>
	 * @param infc
	 * @param entityClass
	 * @return
	 */

	public static <U extends BaseInterface> U beanOf(Class<U> infc, Class<?> entityClass) {
		while (entityClass.getGenericSuperclass() != BasePoEntity.class) {
			entityClass = (Class<?>) entityClass.getSuperclass();
		}
		return (U) beanOf(infc, classResourceName(entityClass));
	};

	/**
	 * 通过 Entity 获取 resourceName
	 * 
	 * @param clazz
	 * @return
	 */
	private static String classResourceName(Class<?> clazz) {
		return InnerUtils.toFirstLowerCase(clazz.getSimpleName());
	}

	/**
	 * 获取一个类实现的 Interface
	 * 
	 * @param clazz
	 * @return
	 */
	private static Set<Class<?>> findInterfacesFromClass(Class<?> clazz) {
		Set<Class<?>> res = new HashSet<>();
		while (clazz != BaseGeneric.class && clazz != Object.class) {
			Stream.of(clazz.getInterfaces())// e
					.filter(ic -> isDirectSubOfBaseInterface(ic))// e
					.forEach(ic -> res.add(ic));
			clazz = clazz.getSuperclass();
		}
		return res;
	}

	/**
	 * 
	 * CGLib 通过提供的 Interface 和 Entity 动态创建类
	 * 
	 * @param targetInterface
	 * @param entityClass
	 * @return
	 * @throws Exception
	 */

	@SuppressWarnings({ "rawtypes", "unchecked" })
	public static BaseGeneric createModule(Class<? extends BaseInterface> targetInterface,
			Class<? extends BasePoEntity> entityClass) throws Exception {
		Enhancer enhancer = new Enhancer();
		enhancer.setSuperclass(INTERFACE_IMPL_MAP.get(targetInterface));
		enhancer.setCallback(NoOp.INSTANCE);
		BaseGeneric o = (BaseGeneric) enhancer.create();
		o.bindEntityClass(entityClass);
		return o;
	}

	/**
	 * interface-resource-this 二层映射
	 */
	private static final Map<String, Map<String, Object>> SRC_SCOPE_MODULE_MAP = new HashMap<>();

	/**
	 * Interface接口-Impl抽象类映射
	 */
	private static final Map<Class<? extends BaseInterface>, Class<? extends BaseInterface>> INTERFACE_IMPL_MAP = findImplements();

	/**
	 * Interface接口-Impl抽象类映射初始化
	 */
	@SuppressWarnings({ "rawtypes", "unchecked" })
	private static Map<Class<? extends BaseInterface>, Class<? extends BaseInterface>> findImplements() {
		return InnerUtils.tryCatch(() -> {
			Map map = new HashMap<>();
			Set<Class<?>> implClasses = ClassUtil.getClasses(ConstSettings.MODULE_IMPL_PACKAGE);
			for (Class<?> temp : implClasses) {
				Class<?> infc = (Class<?>) ((java.lang.reflect.ParameterizedType) temp.getGenericInterfaces()[0])
						.getRawType();
				if (isDirectSubOfBaseInterface(infc)) {
					map.put(infc, temp);
				}
			}
			return map;
		});
	}

	/**
	 * 实例化一个 resourceImpl 类
	 * 
	 * @param temp
	 * @throws Exception
	 */
	public static void createModule(Class<?> temp) throws Exception {
		temp.getConstructor().newInstance();
	}

	/**
	 * 是否是 BaseInterface 的直接子类
	 * 
	 * @param infc
	 * @return
	 */
	private static boolean isDirectSubOfBaseInterface(Class<?> infc) {
		Type[] gics;
		if ((gics = infc.getGenericInterfaces()).length == 0) {
			return false;
		} else {
			return gics[0] == BaseInterface.class;
		}
	}
}
